package cs423.loadBalancer.core;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class WorkerThread implements Runnable{

	
	/*
	 * Worker Thread Class~
	 */
	
	@Override
	public void run() {
		
		Thread [] threads = new Thread[Main.num_threads];
		
		for(int i=0; i<threads.length; i++)
		{
			threads[i] = new Thread(new runJob());
			threads[i].setDaemon(true);

			System.out.println("THREADS "+i+" INSIDE WORKERTHREAD CREATED SUCCESFULLY");
		
			threads[i].start();
		}
		
		try {
			//Main.wt.lock();
			Main.wt_cv.acquire();
		} catch (InterruptedException e) {
			System.out.println("Main.wt_cv.await()");
			e.printStackTrace();
		}	finally{
			
			for(int i=0; i<threads.length; i++)
			{
					try {
						threads[i].join();
					} catch (InterruptedException e) {
						System.out.println("CATCHES IE 44: WT");
						e.printStackTrace();
						threads[i].stop();
					}
			}
			
		}
		
		//new Thread(new waitAdaptor()).start(); NEED OR NOT
		//WE CAN ACCESS NEW THROTTLE VALUE EAACH TIME DUTING RUN JOB
	}
		
	class runJob implements Runnable{
		
		//double sleep_duration=0;
		@Override
		public void run() {
				exec(); 
		}

		private void exec() {
			
		Main.final_result = new ArrayList<Integer>();
			//RUN THE CODE
		while(true){
		
			System.out.println(Main.cut_pos.size());
			
			Main.displayHandler.post(new Runnable(){
				public void run(){
					Main.updateJobsize();
				}
			})	;
			
			if(!Main.cut_pos.isEmpty())
			{
				int pos = Main.cut_pos.remove(0).intValue();
				int height = pos/Main.width;
				int start = pos%Main.width;
				
				long startTime = System.currentTimeMillis();
				
				for(int k=0; k<Main.interval; k++)
				{
					if(start+k<Main.data[0].length)
					{
						double test = (double)Main.multiplier;
						double ori_v = Main.data[height][start+k];
						for(int i=0; i<50000; i++){
						test = ori_v*test;
						test = test/ori_v;
						test = ori_v*test;
						test = test/ori_v;
						}
						/*if(Main.data[height][start+k]==550)
						{
							System.out.println("HEIGHT: "+height+"Width: "+(start+k));
						}*/
						Main.data[height][start+k]*=Main.multiplier;
						//System.out.println(Main.data[height][start+k]);
	}
					else break;
				}
				
				long endTime = System.currentTimeMillis();

				
				long duration = endTime-startTime;
				
				System.out.println("JOB DURATION IS : " + duration);
				
				double sleep_duration=0;
				
				if(Main.throttle!=100)
					sleep_duration = Main.throttle*duration/(double)(100-Main.throttle);
				else
					sleep_duration = duration;
					
				int battery = Main.batteryLevel;
				
				//System.out.println(Main.batteryLevel);
				
				sleep_duration*=(double)(1+(((double)(100-battery))/(double)100));
				
				Main.running_time = duration + sleep_duration;
				
				System.out.println("SLEEP DURATION BEFORE SLEEP: " + sleep_duration);
				try {
					Thread.sleep((long)sleep_duration);
				} catch (InterruptedException e) {
					System.out.println("Thread.sleep(sleep_duration);");
					e.printStackTrace();
				}
				
				System.out.println("SLEEP DURATION AFTER SLEEP: " + sleep_duration);

				
				Main.final_result.add(new Integer(pos));		
				
			}
			else if (Main.other_side_closed)
				//CLOSE MINE
				{
					Main.finish_cv.release();
					return;
				}
			else
				{
				//directly establish a connection to the 
				//other side's state manager, notify it that
				//this connection is finished
				System.out.println(Main.ipAddress + "   WORKER THREAD!");
				Socket s;
				boolean repeat = true;
				
				int tempt=0;
				while(repeat){
				try {
					
					s = new Socket(Main.ipAddress, Main.STATEPORT);
					OutputStream out = s.getOutputStream();
					DataOutputStream dos = new DataOutputStream(out);
					dos.writeInt(Main.WORKER);
					
					//InputStream in=null;
					//in = s.getInputStream();
					//DataInputStream dis = new DataInputStream(in);
					//int result = dis.readInt();
					/*
					if(result==Main.ALIVE)
					{
						//CONNECTION STILL ALIVE
					}
					else
					{
						//CLOSE CONNECTION
						
					}*/
					repeat = false;
					s.close();

					//RIGHT NOW, JUST CLOSE THE MY STUFF
					Main.finish_cv.release();
					return;
											
				} catch (UnknownHostException e) {
					System.out.println("Unknow HOST: Socket s = new Socket(Main.ipAddress, Main.STATEPORT);");
					e.printStackTrace();
					Main.finish_cv.release();
					return;
				} catch (IOException e) {
					System.out.println("IOEXCEPTION: Socket s = new Socket(Main.ipAddress, Main.STATEPORT);");
					e.printStackTrace();
					
					if(tempt>=5){
						Main.finish_cv.release();
						return;
					}
					else 
						tempt++;
					
				}
				
				}//repeat
				
				
				
				}
			
			}
			
		}
		
	
	
	}

	
}
